//
// Created by 卞证 on 2021/05/19.
//
#pragma once

#include <vector>
#include <fstream>
#include <iostream>
#include <ostream>
#include <set>
#include "time_memory.hpp"

namespace SpanTree {

    //the graph index start from 0
    std::vector<std::set<int>> load_efanna(const char *filename) {
        std::vector<std::set<int>> graph;
        std::ifstream in(filename, std::ios::binary);
        unsigned k;
        in.read((char *) &k, 4);
        in.seekg(0, std::ios::end);
        std::ios::pos_type ss = in.tellg();
        size_t fsize = (size_t) ss;
        size_t num = fsize / ((size_t) k + 1) / 4;
        in.seekg(0, std::ios::beg);

        graph.resize(num);
        for (size_t i = 0; i < num; i++) {
            in.seekg(4, std::ios::cur);
            std::vector<int> neighbor_l(k);
            in.read((char *) neighbor_l.data(), k * sizeof(unsigned));
            graph[i].insert(neighbor_l.begin(), neighbor_l.end());
        }
        in.close();
        return graph;
    }

    std::vector<std::pair<int, int>> to_undirected(std::vector<std::set<int>> &graph) {
        int n_vertex = graph.size();
        for (int i = 0; i < n_vertex; i++) {
            for (std::set<int>::iterator iter = graph[i].begin(); iter != graph[i].end(); iter++) {
                int neighbor = *iter;
                if (graph[neighbor].find(i) == graph[neighbor].end()) {
                    graph[neighbor].insert(i);
                }
            }
        }
        std::printf("complete bidirectional undirected\n");
        std::vector<std::pair<int, int>> res_graph;
        int n_edge = 0;
        for (int i = 0; i < n_vertex; i++) {
            for (std::set<int>::iterator iter = graph[i].begin(); iter != graph[i].end(); iter++) {
                int neighbor = *iter;
                if (i < neighbor) {
                    res_graph.push_back(std::make_pair(i, neighbor));
                    n_edge++;
                }
            }
        }
        std::printf("complete single direction\n");
        return res_graph;
    }

    void save_edge_graph(const char *filename, std::vector<std::pair<int, int>> &graph, int n_vertex) {
        std::ofstream out_graph;
        out_graph.open(filename);
        int n_edge = graph.size();
        out_graph << n_vertex << " " << n_edge << std::endl;

        for (int i = 0; i < n_edge; i++) {
            std::pair<int, int> tmp = graph[i];
            out_graph << tmp.first << " " << tmp.second << std::endl;
        }
        out_graph.close();
    }

}